--[[

Formspec string builders for portals

Copyright 2014 Tiberiu CORBU
Authors: Tiberiu CORBU

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
--]]

if not element_portals then
	element_portals = {}
end

local deco = ""
if minetest.global_exists("default") then
	deco = default.gui_bg .. default.gui_bg_img
end


----------------------- Form buider methods

local valid_prefix_channel = function(out_name, in_name)
	
	--  Get input and output chanel
	local in_match = in_name:match('^.*:')
	local out_match = out_name:match('^.*:')

	-- "<channel>:<name>" does not dispay "<other_channel>:<name>"
	if in_match and out_match and in_match ~= out_match then
		return false 
	end

	-- "<name>" can dispay "<channel>:<name>"
	-- -- Unless <name> is not <channel>
	if not in_match and out_match and out_match:sub(1,-2) ~= in_name:gsub('-.*$','') then
		return false
	end

	--  "<channel>:<name>" can dispay "<name>"
	-- -- Unless <name> is not <channel>
	if not out_match and in_match and in_match:sub(1,-2) ~= out_name:gsub('-.*$','') then
		return false
	end

	-- Return true in every other cases
	return true
end

local build_portal_list = function(portals, this_portal_key, selected_portal_name, portal_group)
	-- Declare empty list
	local list = ""
	-- k, v as local (not needed ?)
	local k
	local v
	-- Index start at 1
	local selected_index = 1 -- first by default
	-- Count start at 0
	local count = 0 
	-- For each portal
	for k,v in pairs(portals) do
		-- Get channel prefix
		local check_channel = true
		if portals[this_portal_key] then 
			local this_portal_name = portals[this_portal_key].portal_name
			check_channel = valid_prefix_channel(v.portal_name,this_portal_name)
		end
		-- Is it a registered out portal ?
		local registered = element_portals:is_registered_out_portal(v.node_name, portal_group)
		-- If portal is a registered portal and not the same as selected
		if this_portal_key ~= k and registered and check_channel then	
			
			-- If portal name is same as selected, do not add but increment count
			if v.portal_name == selected_portal_name then
			 	selected_index = count+1
			end
			-- Portal is added to the list
			list = list..v.portal_name..","
			count = count + 1
		end
	end
	-- Return the list ( as a string )
	-- remove the last comma because it adds an empty item into the list,
	-- handled here since lua doensn't have (I dont't know) a cheap count
	-- table method
	if count > 0 then
		list = string.sub(list, 0, -2) 
	end
	return {list=list, selected_index = selected_index}
end

local append_user_inventory_form_fields = function(result, pos)
	local spos = pos.x .. "," .. pos.y .. "," ..pos.z
	result = result.."list[nodemeta:".. spos .. ";fuel;6,3;1,1;]"..
		"list[current_player;main;0,5;8,4;]" ..default.get_hotbar_bg(0,5)..default.gui_slots

	return result
end

local append_current_portal_form_fields = function(result, portal_data, portal_name_editable)
	-- the ones with minus sign are supposed to be hidden
	if portal_data.data then 
    if portal_name_editable then 
      result = result.."field[0.3,1;4,1;portal_name;This portal Name:;"..portal_data.data.portal_name.."]"
		else
      result = result.."field[-8,1;4,1;portal_name;This portal Name:;"..portal_data.data.portal_name.."]"
      result = result.."label[0.3,0.5;".. string.format('%s', portal_data.data.portal_name) .."]"
      local meta = minetest.get_meta(portal_data.data.pos)
      result = result.."label[0.3,1.2;".. string.format('Placed by %s', meta:get_string('owner')) .."]"
    end
    result = result.."field[-6,1;4,1;portal_key;This portal key:;"..portal_data.key.."]"
		result = result.."field[-7,1;4,1;portal_pos;This portal pos:;"..minetest.pos_to_string(portal_data.data.pos).."]"
	else 
		result = result.."label[0.3,1;Can't read portal data]"
	end
	return result
end

local append_active_input_portal_fields = function(result, portal_data, selected_portal_name)
	if portal_data.portals then
		local filter_group, portal_type, list_result
		if portal_data.data then
			portal_type = element_portals:get_portal_type(portal_data.data.node_name)
			filter_group = element_portals:get_portal_filter_group(portal_data.data.node_name)
		end
		if portal_type == element_portals.IN_RANDOM_PORTAL then
			result = result.."label[0,1.8;"..minetest.formspec_escape(" This Portal will teleport you to \n a random place in the world \n ").."]"
			--"textarea[0.3,1.5;5,1.9;rand_text;;"..minetest.formspec_escape("This Portal will teleport you to a random place in the world \n (It could be very far from here)").."]"
		else
			list_result = build_portal_list(portal_data.portals, portal_data.key, selected_portal_name, filter_group);
			result = result.."dropdown[0,2;5;selected_portal_name;"..list_result.list..";"..list_result.selected_index.."]"
		end
		result = result.."button_exit[0,3;5,1;teleport;Teleport]"
	else
		result = result.."label[0.3,1;Can't read portal list]" 
	end
	return result
end

local append_travel_free_fields = function(result)
	result = result.."field[-8,1;4,1;travel_free;Travel Free:;true]"
	return result
end 

-- end form builder methods 


function get_placer_name(pos)
	local meta = minetest.get_meta(pos)
	return meta:get_string("placer")
end

function get_placer(pos)
	local placer_name = get_placer_name(pos)
	if placer_name and placer_name ~= "" then
		 return minetest.get_player_by_name(placer_name)
	end
end

function get_player_portal_data(pos, player, player_name)
  if player then element_portals:sanitize_player_portals(player) end
	local portals = element_portals:read_player_portals_table(player, player_name)
	-- extract portal data for pos and player
	local portal_key = element_portals:construct_portal_id_key(pos, player, player_name)
	local portal_data = portals[portal_key]
	return {portals = portals, key = portal_key, data = portal_data}
end

function get_portal_data(pos, player) 
	local result = get_player_portal_data(pos, player)
	if not result.data then
		-- Try getting data from placer
		local placer_name = get_placer_name(pos)
		local placer = get_placer(pos)
		if placer or placer_name then
			result = get_player_portal_data(pos, placer, placer_name);
		end
	end 
	return result
end


function element_portals:create_portal_formspec(pos, player, selected_portal_name, active, message, portal_name_editable)
	
	local portal_data = get_portal_data(pos, player)

	local result = append_current_portal_form_fields( "size[8,9]"..deco, portal_data, portal_name_editable)
	local result = append_user_inventory_form_fields(result, pos)
	if active then
		result = append_active_input_portal_fields(result, portal_data, selected_portal_name)	
	else
		result = result.."label[0,2;Add element to power the portal]"
	end 
	
	if message then
		result = result.."label[0,4;"..message.."]"		
	end
	return result
end

function element_portals:create_travel_free_portal_formspec(pos, player, selected_portal_name, message, portal_name_editable)
	local portal_data = get_portal_data(pos, player)
	local result = append_current_portal_form_fields("size[5,4]"..deco, portal_data, portal_name_editable)
	result = append_travel_free_fields(result)
	result = append_active_input_portal_fields(result, portal_data, selected_portal_name)	
	if message then
		result = result.."label[0,4;"..message.."]"
	end
	return result
end

function element_portals:create_out_portal_formspec(pos, player, message, portal_name_editable)
	local portal_data = get_portal_data(pos, player)
	local result = append_current_portal_form_fields("size[5,2]"..deco, portal_data, portal_name_editable)
	return result
end

function element_portals:create_item_portal_formspec(player, portal_group, message)
	local portals = element_portals:read_player_portals_table(player)
	-- the ones with minus sign are supposed to be hidden
	local result = "size[5,2]"..deco
		local list_result = build_portal_list(portals, nil, nil, portal_group)
		result = result.."dropdown[0,0;5;selected_portal_name;"..list_result.list..";"..list_result.selected_index.."]"
		result = result.."button_exit[0,1;5,1;teleport;Teleport]"
		result = result.."field[-8,1;4,1;travel_free;Travel Free:;true]"
	return result
end
